package dialog.program;

import java.util.*;

@SuppressWarnings("rawtypes")
class Library 
{
	Map documents = new HashMap();
	Map users = new HashMap();
	Collection loans = new LinkedList();
	final int MAX_NUMBER_OF_LOANS = 20;

	@SuppressWarnings("unchecked")
	public boolean addUser (User user)
	{
		users.remove(new Integer(user.getCode()));
		users.put(new Integer(user.getCode()), user);
		return true;
    }

  	public boolean removeUser(int userCode)
  	{
  		User user = (User)users.get(new Integer(userCode));
  		if (user == null || user.numberOfLoans()>0) return false;
  		else
  		{
  			users.remove(new Integer(userCode));
  			User.usedPositions.remove(userCode);
  			return true;
  		}
  	}

  	public User getUser(int userCode) 
  	{
  		return (User) users.get(new Integer(userCode));
  	}

  	@SuppressWarnings("unchecked")
  	public boolean addDocument(Document doc)
  	{
  		if (!documents.containsValue(doc))
  		{
  			documents.put(new Integer(doc.getCode()),doc);
  			return true;
  		}
  		else return false;
  	}

  	public boolean removeDocument(int docCode)
  	{
  		Document doc = (Document)documents.get(new Integer(docCode));
  		if (doc == null || doc.isOut()) return false;
  		else
  		{
  			documents.remove(new Integer(docCode));
  			Document.usedPositions.remove(docCode);		
  			return true;
  		}
  	}

  	public Document getDocument(int docCode) 
  	{
  		return (Document)documents.get(new Integer(docCode));
  	} 

  	@SuppressWarnings("unchecked")
  	private void addLoan(Loan loan) 
  	{
		if (loan == null) return;
		else
		{
			User user = loan.getUser();
			Document doc = loan.getDocument();
			loans.add(loan);
			user.addLoan(loan);
			if (doc.getType() == "journal")
			{
				doc.addLoanForJournal(loan);
			}
			else doc.addLoan(loan);
		}
  	}

  	private void removeLoan(Loan loan) 
  	{
  		if (loan == null) return;
  		else
  		{
  			Document doc = loan.getDocument();
  			loans.remove(loan);
  			if (doc.getType() == "journal")
  			{
  				doc.removeLoanForJournal(loan);
  			}
  			else doc.removeLoan();
  		}  		
  	}

  	public boolean borrowDocument(User user, Document doc) 
  	{
  		if (doc.getType() == "journal" && user.numberOfLoans() < MAX_NUMBER_OF_LOANS)
  		{
  			Loan loan = new Loan(user, doc);
  			addLoan(loan);
  			return true;  			
  		}
  		else if (user.numberOfLoans() < MAX_NUMBER_OF_LOANS && doc.isAvailable()) 
  		{
  			Loan loan = new Loan(user, doc);
  			addLoan(loan);
  			return true;
  		}
  		else return false;
  	}

  	public boolean returnDocument(Document doc) 
  	{  
  		if (doc == null) return false;
  		else if (doc.isOut()) 
  		{
  			User user = doc.getBorrower();
  			Loan loan = new Loan(user, doc);
  			removeLoan(loan);
  			return true;
  		}
  		else return false;
  	}

  	public boolean isHolding(User user, Document doc) 
  	{
  		if (user == null || doc == null) return false;
  		else return loans.contains(new Loan(user, doc));
  	}

  	@SuppressWarnings("unchecked")
  	public List searchUser(String name) 
  	{
  		List userFound = new LinkedList();
  		Iterator i = users.values().iterator();
  		while (i.hasNext()) 
  		{
  			User user = (User)i.next();
  			if (user.getName().indexOf(name) != 1)
  				userFound.add(user);
  		}
  		return userFound;
  	}
  	
  	@SuppressWarnings("unchecked")
  	public List searchDocumentByTitle(String title) 
	{
		List docsFound = new LinkedList();
		Iterator i = documents.values().iterator();
		while (i.hasNext()) 
		{
			Document doc = (Document)i.next();
			if (doc.getTitle().indexOf(title) != -1)
				docsFound.add(doc);
		}
		return docsFound;
	}
	
  	@SuppressWarnings("unchecked")
	public List searchDocumentByAuthors(String authors) 
	{
		List docsFound = new LinkedList();
		Iterator i = documents.values().iterator();
		while (i.hasNext()) 
		{
			Document doc = (Document)i.next();
			if (doc.getAuthors().indexOf(authors) != -1)
				docsFound.add(doc);
		}
		return docsFound;
	}
	
	public int searchDocumentByISBN(String isbn) 
	{
		Iterator i = documents.values().iterator();
		while (i.hasNext()) 
		{
			Document doc = (Document)i.next();
			if (isbn. equals (doc. getISBN()))
				return doc.getCode();
		}
		return -1;
	}
	
	public void printAllLoans() 
	{
		Iterator i = loans.iterator();
		while (i.hasNext()) 
		{
			Loan loan = (Loan)i.next();
			loan.print();
		}
	}
}
